package com.hm.rabitmq.rpc;

import com.rabbitmq.client.AMQP.BasicProperties;

import java.util.UUID;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;

/**
 * @author shishun.wang
 * @date 2016年12月12日 下午4:46:16
 * @version 1.0
 * @describe
 */
public class RpcServer {

	private static final String RPC_QUEUE_NAME = "RPC_QUEUE";

	public static void main(String[] args) {
		Connection connection = null;
		try {
			ConnectionFactory factory = new ConnectionFactory();
			factory.setHost("115.28.66.183");

			connection = factory.newConnection();
			Channel channel = connection.createChannel();

			channel.queueDeclare(RPC_QUEUE_NAME, false, false, false, null);
			channel.basicQos(1);// 公平发送，处理完了当前任务才能获取下一个任务

			QueueingConsumer consumer = new QueueingConsumer(channel);
			channel.basicConsume(RPC_QUEUE_NAME, false, consumer);

			System.out.println("waiting for RPC requests...");
			while (true) {
				QueueingConsumer.Delivery delivery = consumer.nextDelivery();

				// 获取客户端请求基本信息
				BasicProperties props = delivery.getProperties();

				// 设置响应属性
				BasicProperties replyProps = new BasicProperties().builder().correlationId(props.getCorrelationId())// 关联id
						.build();

				String message = new String(delivery.getBody(), "UTF-8");
				int n = Integer.parseInt(message);

				System.out.println("start to handler fib(" + message + ")");
				String response = UUID.randomUUID() + "-----" + fibonacci(n) + "-----" + System.currentTimeMillis();

				// 响应客户端
				channel.basicPublish("", props.getReplyTo(), replyProps, response.getBytes("UTF-8"));
				channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (connection != null) {
				try {
					connection.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 计算fibonacci(斐波那契数列)前n项和
	 */
	private static int fibonacci(int n) {
		if (n == 1 || n == 2) {
			return 1;
		}
		return fibonacci(n - 1) + fibonacci(n - 2);
	}
}
